from flask import jsonify, request
from flask_login import current_user
from flask_restful import Resource, marshal_with, reqparse  # type: ignore
from controllers.errors.character_errors import HTTPCharacterCreateParamError, HTTPCharacterNotExistError
from controllers.errors.emoji_errors import HTTPEmojiPackNotExistError
from controllers.errors.timbre_errors import HTTPTimbreNotExistError
from core.roles.role_check import check_perms
from libs.helper import extract_remote_ip
from libs.login import login_required
from controllers.console import api
from services.errors.character import CharacterCreateParamError, CharacterNotExistError
from services.errors.emoji import EmojiPackageNotExistError
from services.errors.timbre import TimbreNotExistError
from services.robot.character_service import CharacterService
from fields.character_fields_def import character_fields,character_list_fields
from werkzeug.exceptions import BadRequest

class CharacterManangeApi(Resource):
    @login_required
    @check_perms(perms=['character:list'])
    @marshal_with(character_list_fields)
    def get(self):
        argparser = reqparse.RequestParser()
        argparser.add_argument("id",type=str,required=False,location='args')
        argparser.add_argument("name",type=str,required=False,location='args')
        argparser.add_argument("personality",type=str,required=False,location='args')
        argparser.add_argument("timbre_id",type=str,required=False,location='args')
        argparser.add_argument("emoji_pack_id",type=str,required=False,location='args')
        argparser.add_argument("page",type=int,required=False,default=-1,location='args')
        argparser.add_argument("page_size",type=int,required=False,default=-1,location='args')
        args = argparser.parse_args()
        return  CharacterService.get_character_list(current_user.current_tenant_id,args)
    
    @login_required
    @check_perms(perms=['character:new'])
    @marshal_with(character_fields)
    def post(self):
        argparser = reqparse.RequestParser()
        argparser.add_argument("name",type=str,required=True,location='json')
        argparser.add_argument("personality",type=str,required=False,location='json')
        argparser.add_argument("agent_id",type=str,required=True,location='json')
        argparser.add_argument("default_timbre_id",type=str,required=True,location='json')
        argparser.add_argument("default_emoji_pack_id",type=str,required=True,location='json')
        argparser.add_argument("appearance_url",type=str,required=False,location='json')
        argparser.add_argument("appearance_file_id",type=str,required=False,location='json')
        argparser.add_argument("greet_sentence",type=str,required=False,location='json')
        argparser.add_argument("wakeup_sentences",type=str,action='append',required=False,location='json')
        argparser.add_argument("busy_sentences",type=str,action='append',required=False,location='json')
        argparser.add_argument("stepback_sentences",type=str,action='append',required=False,location='json')
        args = argparser.parse_args()
        try:
            character =  CharacterService.create_character(current_user,args,extract_remote_ip(request))
            return character
        except EmojiPackageNotExistError as e:
            raise HTTPEmojiPackNotExistError(emoji_pack_id=e.emoji_pack_id)
        except CharacterCreateParamError as e:
            raise HTTPCharacterCreateParamError(message=e.description)
        except TimbreNotExistError as e:
            raise HTTPTimbreNotExistError(timbre_id=e.timbre_id)
        except Exception as e:
            raise BadRequest(description=str(e))
        
    @login_required
    @check_perms(perms=['character:update'])
    @marshal_with(character_fields)
    def put(self):
        argparser = reqparse.RequestParser()
        argparser.add_argument("id",type=str,required=True,location='json')
        argparser.add_argument("name",type=str,required=True,location='json')
        argparser.add_argument("personality",type=str,required=False,location='json')
        argparser.add_argument("agent_id",type=str,required=True,location='json')
        argparser.add_argument("default_timbre_id",type=str,required=True,location='json')
        argparser.add_argument("default_emoji_pack_id",type=str,required=True,location='json')
        argparser.add_argument("price",type=float,required=False,location='json')
        argparser.add_argument("appearance_url",type=str,required=False,location='json')
        argparser.add_argument("appearance_file_id",type=str,required=False,location='json')
        argparser.add_argument("greet_sentence",type=str,required=False,location='json')
        argparser.add_argument("wakeup_sentences",type=str,action='append',required=False,location='json')
        argparser.add_argument("busy_sentences",type=str,action='append',required=False,location='json')
        argparser.add_argument("stepback_sentences",type=str,action='append',required=False,location='json')
        args = argparser.parse_args()
        try:
            character =  CharacterService.update_character(current_user,args,extract_remote_ip(request))
            return character
        except CharacterNotExistError as e:
            raise HTTPCharacterNotExistError(character_id=e.character_id)
        except CharacterCreateParamError as e:
            raise HTTPCharacterCreateParamError(message=e.description)
        except TimbreNotExistError as e:
            raise HTTPTimbreNotExistError(timbre_id=e.timbre_id)
        except EmojiPackageNotExistError as e:
            raise HTTPEmojiPackNotExistError(emoji_pack_id=e.emoji_pack_id)
        except Exception as e:
            raise BadRequest(description=str(e))
        
    @login_required
    @check_perms(perms=['character:del'])
    def delete(self):
        argparser = reqparse.RequestParser()
        argparser.add_argument("id",type=str,required=True,location='json')
        args = argparser.parse_args()
        character_id = args.get("id",None)
        if not character_id:
            raise HTTPCharacterCreateParamError(message="character_id is required")
        try:
            CharacterService.del_character(current_user,character_id,extract_remote_ip(request))
            return jsonify(
                {
                    "code": 200,
                    "status": "success",
                }
            )
        except CharacterNotExistError as e:
            raise HTTPCharacterNotExistError(e.character_id)
        except Exception as e:
            raise BadRequest(description=str(e))
        
api.add_resource(CharacterManangeApi, "/characters")